#! /usr/bin/python

'''

This file accepts a S-Expression as a string and converts it into a 
CodeTree for this project. This does almost no processing on the
S-Expression. The Syntatic sugar is removed in the SExpression class,
and the CodeTreeTo... classes determine how to interpret the code tree
with hints from CodeTree itself. This just looks at the SExpression
and builds a tree structure exactly representing it.

@author kllvql
@date 12/23/11

'''

from ProjectFlags import *

#TEST  = True
TEST  = False
#DEBUG = True
DEBUG = False


TEST  = TEST  or TEST_ALL
DEBUG = DEBUG or DEBUG_ALL


	
from SExpression import SExpression
from CodeTree import CodeTree

class SExpressionToCodeTree:
	'''
	Accepts SExpressions which are well formatted according to the 
	standards included with this project.
	'''
	
	def __init__(self, sExp=None):
		'''
		If the sExpression is non-None, this will build the requisite
		CodeTree off of the sExpression to properly store the code in 
		memory. If you don't initalize it with an SExpression, you 
		can call the setSExpression function to set the expression
		to use.
		'''
		if sExp != None:
			self._loadSExpression(sExp)
	
	def __str__(self):
		return str(self.codeTree)
	
	def setSExpression(self, sExp):
		'''
		Allows you to reset the SExpression used for this CodeTree. 
		The CodeTree is then reloaded. 
		'''
		self._loadSExpression(sExp)

	def _loadSExpression(self, sExp):
		'''
		Requires that the list be non-empty, with the first element not
		being a list and serving as the root element of the tree
		'''
		if DEBUG:
			print "_loadSExpression typeof sExp: " + str(type(sExp))
		self.codeTree = CodeTree(str(sExp.car()),
								 str(sExp.cdr().caar()))
		sExp = sExp.cdr().cadr()
		self._addElements(self.codeTree.getMain(), sExp)
	
	def _addElements(self, node, sExp):
		'''
		Adds the elements in sExpression as children of node. This
		is useful for the cdr of an original list. eg. car(list) = node,
		cdr(list) = sExp
		'''
		for element in sExp.iterate():
			if element.isList():
				newNode = CodeTree.getNode(str(element.car()))
				node.addChild(newNode)
				self._addElements(newNode, element.cdr())
			else:
				newNode = CodeTree.getNode(str(element))
				node.addChild(newNode)
				return node
	
	def getCodeTree(self):
		'''
		Returns the codeTree loaded off of this class. 
		'''
		return self.codeTree


def test():
	print "SExpressionToCodeTree.py testing..."
	
	s =  '(Character (name (type string)) (age (type (range (min 10) '
	s += '(max 20)))) (inventory (type bag)))'
	print s
	sExp = SExpression(s)
	ct = SExpressionToCodeTree(sExp)
	print ct
	
	print "End SExpressionToCodeTree.py testing.\n"

if __name__ == '__main__' or TEST:
	test()
